/**
 * Copyright (c) 2006-2013 Las Venturas Mineground
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program.
 * If not, see <http://www.gnu.org/licenses/>.
 */

package org.mineground.commands;

import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.permissions.Permission;

/**
 * An command can originate from one of three origins: a player who typed /CommandName, someone with
 * access to the server's console who types "CommandName", or someone on IRC typing "!CommandName".
 * A number of proxy methods are provided for ease of use.
 * 
 * The CommandOrigin class deliberately does not provide access to the abstract CommandSender value,
 * and instead provides three specialized getters: getPlayer(), getConsole() and getIrcUser(). When
 * calling the getPlayer() method while the origin is the console, an error will be issued and NULL
 * will be returned. As such, always do NULL-checking on the return values.
 */
public class CommandOrigin {
    private CommandSender mSender;
    private CommandOriginType mType;
    
    /**
     * Initializes a new Command Origin object for the given sender. We'll determine the type of
     * origin in here, and store the variables in our class scope.
     * 
     * @param sender The origin which issued a command.
     */
    public CommandOrigin(CommandSender sender) {
        this.mSender = sender;
        this.mType = CommandOriginType.PLAYER;
        
        if (sender instanceof ConsoleCommandSender)
            this.mType = CommandOriginType.CONSOLE;
        
        // TODO: Recognize commands originating from IRC.
    }
    
    /**
     * Returns the name of the entity which sent this command. If the sender is a Player, their
     * nickname will be returned. If it's a console sender, either "CONSOLE" for the local console
     * will be returned, or "Rcon" in case it's a remote console command.
     * 
     * @return A textual representation of the origin of this command.
     */
    public String getName() {
        return mSender.getName();
    }
    
    /**
     * Distributes a message to the command's origin.
     * 
     * @param message The message which should be send to the originator.
     */
    public void sendMessage(String message) {
        mSender.sendMessage(message);
    }
    
    /**
     * Distributes a series of messages to the command's origin.
     * 
     * @param message The message which should be send to the originator.
     */
    public void sendMessage(String[] message) {
        mSender.sendMessage(message);
    }
    
    /**
     * Determine whether the command's origin has a certain permission.
     * 
     * @param permission The permission which we'd like to know the status of.
     * @return A boolean indicating whether the origin has this permission.
     */
    public boolean hasPermission(Permission permission) {
        return mSender.hasPermission(permission);
    }
    
    /**
     * Determine whether the command's origin is a Server Operator. Operators generally have all
     * rights and do not need additional permission checking. Console senders are seen as operators,
     * senders originating from IRC never are.
     * 
     * @return A boolean indicating whether the origin is a server operator.
     */
    public boolean isOperator() {
        return mSender.isOp();
    }
    
    /**
     * Return the Player object who sent this command. If the sender of this command is not a
     * player, then an error will be logged and NULL will be returned.
     * 
     * @return The player who sent this command, or NULL.
     */
    public Player getPlayer() {
        if (mType == CommandOriginType.PLAYER)
            return (Player) mSender;
        
        // TODO: Log that we're returning a wrong type.
        return null;
    }
    
    /**
     * Returns the Console object who sent this command. If the sender of this command is not a
     * console, an error will be logged and NULL will be returned.
     * 
     * @return The console who sent this command, or NULL.
     */
    public ConsoleCommandSender getConsole() {
        if (mType == CommandOriginType.CONSOLE)
            return (ConsoleCommandSender) mSender;
        
        // TODO: Log that we're returning a wrong type.
        return null;
    }
    
    /**
     * Returns the IRC User object who sent this command. If the sender of this command is not an
     * IRC user, an error will be logged and NULL will be returned.
     * 
     * @return The IRC user who sent this command, or NULL.
     */
    public Object getIrcUser() {
        // TODO: Implement retrieval of IRC users.
        return null;
    }
    
    /**
     * Returns the type of command which was issued, allowing the caller to determine whether it
     * should invoke getPlayer() or otherwise.
     * 
     * @return The type of command which was issued.
     */
    public CommandOriginType getType() {
        return mType;
    }
}
